package com.boyinet.demo.pipelineleakage.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.boyinet.demo.pipelineleakage.bean.primary.PipeLine;
import com.boyinet.demo.pipelineleakage.bean.primary.Sensor;
import com.boyinet.demo.pipelineleakage.common.AppFileUtils;
import com.boyinet.demo.pipelineleakage.common.R;
import com.boyinet.demo.pipelineleakage.common.Tree;
import com.boyinet.demo.pipelineleakage.repository.primary.PipeLineRepository;
import com.boyinet.demo.pipelineleakage.vo.PipelineSearchParams;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.map.HashedMap;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author lengchunyun
 */
@Service
@Slf4j
public class PipeLineService {

    private final PipeLineRepository pipeLineRepository;
    private final SensorService sensorService;
    private final SchedulerJobService schedulerJobService;

    private final static String JOB_CONTENT_TEMPLATE = "[%s]泄漏定时计算";

    public PipeLineService(PipeLineRepository pipeLineRepository, SensorService sensorService, SchedulerJobService schedulerJobService) {
        this.pipeLineRepository = pipeLineRepository;
        this.sensorService = sensorService;
        this.schedulerJobService = schedulerJobService;
    }

    public void save(PipeLine pipeLine) {
        String renameFile = AppFileUtils.renameFile(pipeLine.getXlsFileName());
        pipeLine.setXlsFileName(AppFileUtils.uploadPath + renameFile);
        PipeLine save = pipeLineRepository.save(pipeLine);
        log.info("[XLSX 文件]，文件路径{}", pipeLine.getXlsFileName());
        sensorService.readFileAndSave(AppFileUtils.uploadPath + renameFile, save.getId());
    }

    public Page<PipeLine> list(PipelineSearchParams params) {
        return pipeLineRepository.findAll((Specification<PipeLine>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            if (StrUtil.isNotBlank(params.getName())) {
                list.add(criteriaBuilder.like(root.get("name").as(String.class), "%" + params.getName() + "%"));
            }
            if (null != params.getStandard()) {
                list.add(criteriaBuilder.equal(root.get("standard").as(Double.class), params.getStandard()));
            }
            if (null != params.getDuration()) {
                list.add(criteriaBuilder.equal(root.get("duration").as(Double.class), params.getDuration()));
            }
            return criteriaBuilder.and(list.toArray(new Predicate[]{}));
        }, PageRequest.of(params.getPage() - 1, params.getLimit()));

    }

    public void deleteById(Long id) {
        sensorService.deleteByPipeLineId(id);
        schedulerJobService.deleteByPipelineId(id);
        pipeLineRepository.deleteById(id);
    }

    public void updateById(PipeLine pipeLine) {
        pipeLineRepository.findById(pipeLine.getId()).ifPresent(old -> {
            BeanUtil.copyProperties(pipeLine, old, CopyOptions.create(PipeLine.class, true));
            pipeLineRepository.save(old);
        });

    }

    public List<Tree> tree() {
        List<Tree> trees = new ArrayList<>();
        Iterable<PipeLine> all = pipeLineRepository.findAll();
        all.forEach(pipeLine -> trees.add(new Tree(pipeLine.getName(), pipeLine.getId(), true)));
        return trees;
    }

    public PipeLine load(Long id) {
        PipeLine pipeLine = pipeLineRepository.findById(id).orElse(null);
        if (pipeLine == null) {
            return null;
        }
        List<Sensor> sensorList = sensorService.findByPid(id);
        pipeLine.setSensorList(sensorList);
        return pipeLine;
    }

    public PipeLine findById(Long pipelineId) {
        return pipeLineRepository.findById(pipelineId).orElse(null);
    }

    public List<PipeLine> findAll() {
        List<PipeLine> pipeLines = new ArrayList<>();
        pipeLineRepository.findAll().forEach(pipeLines::add);
        return pipeLines;
    }

    public R<Map<String, Map<String, String>>> listPipelineMap() {
        Map<String, Map<String, String>> data = new HashedMap<>(6);
        List<PipeLine> pipeLines = pipeLineRepository.findAll(null);
        if (CollectionUtil.isNotEmpty(pipeLines)) {
            Map<String, String> selectItems = pipeLines.stream()
                    .collect(Collectors.toMap(p -> String.valueOf(p.getId()), PipeLine::getName));
            data.put("selectItems", selectItems);

            List<Long> ids = schedulerJobService.listPipelineIds();
            Map<String, String> jobItemsMap = pipeLines.stream().filter(s -> !ids.contains(s.getId()))
                    .collect(Collectors.toMap(p -> String.valueOf(p.getId()), p -> String.format(JOB_CONTENT_TEMPLATE, p.getName())));
            data.put("jobItems", jobItemsMap);
        }
        R<Map<String, Map<String, String>>> result = R.ok(data);
        result.setTotal(pipeLines.size());
        return result;
    }

    public Map<String, String> listSensorMap(Long pipelineId) {
        Map<String, String> sensorMap = new HashedMap<>();
        pipeLineRepository.findById(pipelineId).ifPresent(pipeLine -> sensorMap.putAll(pipeLine.getSensorList()
                .stream().collect(Collectors.toMap(s -> s.getId().toString(), s -> s.getId().toString()))));
        return sensorMap;
    }
}
